home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 011 / vtreeh.arc / VTREEH.ASM next >
Encoding:
Assembly Source File  |  1987-04-23  |  14.4 KB  |  311 lines

  1. ;       VTREE -- A Visual Tree-structured subdirectory list
  2. ;       =====
  3. ;
  4. ;               (c) copyright Charles Petzold, 1985
  5. ;
  6. ;               Assembler file: COM format
  7. ;               Requirements:   DOS 2.0 or higher
  8. ;               Parameters:     Optional Drive Specification
  9. ;
  10. ;               From PC Magazine
  11. ;
  12. ;               Modified 2/25/87 by David Polansky to also show
  13. ;                        and mark hidden subdirectories (hidden
  14. ;                        subdirectories are followed by a *)
  15.  
  16. CSEG            Segment
  17.                 Assume  CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
  18.  
  19.                 Org     005Ch
  20. FCB             Label   Byte            ; Will contain drive parameter
  21.  
  22.                 Org     0080h
  23. DefaultDTA      Label   Byte            ; Used for look-ahead searches
  24.  
  25.                 Org     0100h
  26. Entry:          Jmp     Begin           ; Program entry point
  27.  
  28. ;       Most Data
  29. ;       ---------
  30.  
  31. SearchAsciiz    db      ?,":\*.*",0             ; ? gets drive spec
  32.  
  33.                 db      '(C) Copyright Charles Petzold, 1985'
  34.  
  35. DriveError:     db      'Invalid disk drive$'   ; Error message
  36. DosVersError    db      'Requires DOS 2.0 +$'   ; Another error message
  37.  
  38. FirstOrNext     db      0                       ; Flag for searches
  39. LevelsIn        dw      0                       ; Directory level (0 = root)
  40. SearchString    db      "\*.*",0                ; Asciiz for "all files"
  41. SearchPointer   dw      3 + Offset SearchAsciiz ; End of SearchAsciiz string
  42. DtaPointer      dw      Offset EndProg          ; Place for current DTA
  43. DashCount       dw      ?                       ; For horizontal line count
  44. HiddenMark      db      42                      ; Mark for hidden subdir (*)
  45.  
  46. ;       Check drive validity and DOS Version
  47. ;       ------------------------------------
  48.  
  49. Begin:          Cmp     AL,0FFh         ; Check for Valid Drive Specification
  50.                 Jnz     DriveSpecOK     ; If OK, proceed
  51.  
  52.                 Lea     DX,DriveError   ; Otherwise print an error message!
  53. ErrorExit:      Mov     AH,9            ; Print string
  54.                 Int     21h             ;   by calling DOS
  55.  
  56.                 Int     20h             ; And exit
  57.  
  58. DriveSpecOK:    Mov     AH,30h          ; Use DOS to get the
  59.                 Int     21h             ;   Version Number
  60.  
  61.                 Cmp     AL,2            ; See if it's 2.0 or above
  62.                 Jae     DosVersOK       ; If so, proceed
  63.  
  64.                 Lea     DX,DosVersError ; Otherwise print an error message!
  65.                 Jmp     ErrorExit       ; Print message & exit
  66.  
  67. ;       Get disk drive for tree
  68. ;       -----------------------
  69.  
  70. DosVersOK:      Mov     AL,[FCB]        ; Get drive parameter from FCB
  71.                 Or      AL,AL           ; See if it's zero (default)
  72.                 Jnz     NotDefault      ; If not, skip a few instructions
  73.  
  74.                 Mov     AH,19h          ; Get default drive
  75.                 Int     21h             ;   by calling DOS
  76.  
  77.                 Inc     AL              ; Turns drive A: = 0 to drive A: = 1
  78.  
  79. NotDefault:     Mov     DL,AL           ; Set DL to drive number (A: = 1)
  80.                 Add     AL,'@'          ; Convert to character "A", etc
  81.                 Mov     [SearchAsciiz],AL       ; Put it in our search string
  82.                 Cld                     ; All string directions forward
  83.  
  84. ;       Do *.* search for sub-directories
  85. ;       ---------------------------------
  86.  
  87. MainLoop:       Mov     DX,[DTAPointer]         ; Get current DTA address
  88.                 Mov     AH,1Ah                  ; Set the DTA
  89.                 Int     21h                     ;   by calling DOS
  90.  
  91.                 Mov     BX,[LevelsIn]           ; BX represents level
  92.                 Add     BX,BX                   ; Double it for addressing
  93.                 Cmp     [FirstOrNext],0         ; See if this is first search
  94.                 Jnz     FindNextFile            ; If not, skip some code
  95.  
  96.                 Mov     Word Ptr [SubDirCounter + BX],0 ; Count starts at 0
  97.  
  98.                 Mov     DX,Offset SearchAsciiZ  ; Directory to search for
  99.                 Mov     CX,12h                  ; Directory attribute search
  100.                                                 ; change here
  101.                 Mov     AH,4Eh                  ; Find first file
  102.                 Int     21h                     ;   by calling DOS
  103.  
  104.                 Jmp     Short TestMatch         ; See if we've got match
  105.  
  106. FindNextFile:   Mov     AH,4Fh                  ; Otherwise find next file
  107.                 Int     21h                     ;   by calling DOS
  108.  
  109. TestMatch:      Jnc     TestAttr                ; If CY flag not set, continue
  110.                 Jmp     NoMoreFiles             ; Otherwise, no more files
  111.  
  112. TestAttr:       Mov     SI,[DTAPointer]         ; SI now points to DTA
  113.                 Cmp     Byte Ptr [SI + 21],10h  ; Test if a directory
  114.                 Jz      FoundDirEntry           ; If it is move on
  115.                 Cmp     Byte Ptr [SI + 21],12h  ; Test if hidden directory
  116.                 Jnz     FindNextFile            ; If not, loop up for next
  117.  
  118. FoundDirEntry:  Add     SI,30                   ; SI points to directory name
  119.                 Cmp     Byte Ptr [SI],'.'       ; See if it's . or .. entry
  120.                 Jz      FindNextFile            ; If so, loop up for next
  121.  
  122. ;       Have found a valid directory entry
  123. ;       ----------------------------------
  124.  
  125.                 Inc     Word Ptr [SubDirCounter + BX]   ; Got another one
  126.                 Mov     CX,[LevelsIn]           ; Number of levels deep
  127.                 Jcxz    LookAheadSearch         ; If root, skip indentation
  128.  
  129.                 Cmp     Word Ptr [SubDirCounter + BX],1 ; See if first found
  130.                 Jz      NoSpaceIn               ; If so, no indentations
  131.  
  132.                 Sub     BX,BX                   ; Start index at zero
  133.  
  134. IndentLoop:     Mov     AL,179                  ; Vertical line character
  135.                 Test    Word Ptr [SubDirCounter + BX],8000h
  136.                 Jz      GotContinueChar         ; Use if still more dirs left
  137.  
  138.                 Mov     AL,' '                  ; Otherwise use a blank
  139. GotContinueChar:Call    PrintChar               ; And print it
  140.  
  141.                 Push    CX                      ; Save the levels count
  142.  
  143.                 Mov     CX,16                   ; Need 16 blanks indentation
  144. BlankLoop:      Mov     AL,' '                  ; This is the blank
  145.                 Call    PrintChar               ; We print it
  146.                 Loop    BlankLoop               ; And loop for the next
  147.  
  148.                 Pop     CX                      ; Retrieve the levels count
  149.  
  150.                 Inc     BX                      ; Kick up the levels index
  151.                 Inc     BX                      ; Twice because word access
  152.  
  153.                 Loop    IndentLoop              ; Loop for all the levels
  154.  
  155. NoSpaceIn:      Cmp     Word Ptr [SubDirCounter + BX],1 ; See if first one
  156.                 Jnz     LookAheadSearch         ; If not skip a little
  157.  
  158.                 Mov     CX,[DashCount]          ; Number of lines to print
  159. DashPrint:      Mov     AL,196                  ; Horizontal line character
  160.                 Call    PrintChar               ; Print them
  161.                 Loop    DashPrint               ; And loop for whole count
  162.  
  163. ;       Check for more directories to determine proper line characters
  164. ;       --------------------------------------------------------------
  165.  
  166. LookAheadSearch:Push    SI                      ; Save ptr to directory name
  167.  
  168.                 Mov     SI,[DtaPointer]         ; Set source to DTA
  169.                 Mov     DI,Offset DefaultDTA    ; Set destination to 80h
  170.                 Mov     DX,DI                   ; Also DX (used later)
  171.                 Mov     CX,43                   ; 43 characters to transfer
  172.                 Rep     Movsb                   ; Move them in
  173.  
  174.                 Pop     SI                      ; Get back directory name ptr
  175.  
  176.                 Mov     AH,1Ah                  ; Set a new DTA
  177.                 Int     21h                     ;   by calling DOS
  178.  
  179. CheckIfAnyMore: Mov     AH,4Fh                  ; Find the next file
  180.                 Int     21h                     ;   by calling DOS
  181.                 Jc      CantFindAnother         ; CY set if can't find one
  182.  
  183.                 Cmp     Byte Ptr [DefaultDTA + 21],10h  ; Test if a directory
  184.                 Jz      GotOne                  ; It is one
  185.  
  186.                 Cmp     Byte Ptr [DefaultDTA + 21],12h ;Test if hidden directory
  187.                 Jnz     CheckIfAnyMore          ; If not, gotta try again
  188.  
  189. GotOne:         Mov     AL,194                  ; Horizontal w/ vertical below
  190.                 Cmp     Word Ptr [SubDirCounter + BX],1
  191.                 Jz      GotGoodChar             ; This is good if it's first
  192.  
  193.                 Mov     AL,195                  ; Vertical w/ horizontal right
  194.                 Jmp     Short GotGoodChar       ; Other than first found
  195.  
  196. CantFindAnother:Mov     AL,196                  ; Horizontal line character
  197.                 Cmp     Word Ptr [SubDirCounter + BX],1
  198.                 Jz      GotGoodChar             ; This is good if first one
  199.  
  200.                 Mov     AL,192                  ; Lower left corner
  201.                 Or      Word Ptr [SubDirCounter + BX],8000h     ; Flag no more
  202.  
  203. GotGoodChar:    Call    PrintChar               ; Print that character also
  204.  
  205.                 Mov     AL,196                  ; Horizontal line character
  206.                 Call    PrintChar               ; Another print
  207.  
  208.                 Mov     AL,' '                  ; Space before file name
  209.                 Call    PrintChar               ; Print the space
  210.  
  211. ;       Now print name of directory and append to SearchPointer string
  212. ;       --------------------------------------------------------------
  213.  
  214.                 Mov     CX,13           ; Number of characters in name
  215.                 Mov     DI,[SearchPointer]      ; End of current search asciiz
  216.  
  217. PrintNameLoop:  Lodsb                   ; Get the directory name character
  218.                 Or      AL,AL           ; Check if it's zero terminator
  219.                 Jz      EndOfName       ; If so, we're at the end
  220.  
  221.                 Stosb                   ; Save on end of search asciiz
  222.                 Call    PrintChar       ; And print it also
  223.  
  224.                 Loop    PrintNameLoop   ; Loop for maximum number of chars
  225.  
  226. EndOfName:      Mov     AL,' '          ; Stick a blank at the end
  227.                 Mov     SI,[DTAPointer]
  228.                 Cmp     Byte Ptr [SI + 21],12h ;Test if hidden directory
  229.                 Jnz     NowPrint
  230.                 Mov     AL,HiddenMark
  231. NowPrint:       Call    PrintChar       ; Print the blank
  232.                 Mov     [DashCount],CX  ; Save for later dashes at end
  233.  
  234. FixUpSearch:    Mov     [SearchPointer],DI      ; New end of asciiz string
  235.                 Inc     [SearchPointer]         ; Point to next character
  236.                 Mov     SI,Offset SearchString  ; Will move in \*.*,0 string
  237.                 Mov     CX,5                    ; It's only five characters
  238.                 Rep     Movsb                   ; Move it ine
  239.  
  240.                 Inc     [LevelsIn]              ; We're one level deeper now
  241.                 Mov     [FirstOrNext],0         ; Prepare for search first
  242.                 Add     [DtaPointer],43         ; New DTA will be needed
  243.                 Jmp     MainLoop                ; Back up to beginning
  244.  
  245. ;       When no more files are found, time to back up to previous subdirectory
  246. ;       ----------------------------------------------------------------------
  247.  
  248. NoMoreFiles:    Cmp     [LevelsIn],0            ; See if we're back in root
  249.                 Jz      Terminate               ; If so, we're all done!
  250.  
  251.                 Test    Word Ptr [SubDirCounter + BX],7FFFh
  252.                 Jnz     BackUpOneDir            ; If at least one file found
  253.  
  254.                 Mov     AL,13                   ; A carriage return
  255.                 Call    PrintChar               ;   is printed
  256.                 Mov     AL,10                   ; A line feed
  257.                 Call    PrintChar               ;   makes a new line
  258.  
  259. BackUpOneDir:   Mov     DI,Offset SearchAsciiz  ; Let's look at search string
  260.                 Mov     CX,70                   ; It could have 70 characters
  261.                 Mov     AL,0                    ; We'll search for a zero
  262.                 Repnz   Scasb                   ; Let's do it
  263.  
  264.                 Dec     DI                      ; So points to zero
  265.  
  266.                 Mov     CX,64                   ; Now we'll search backwards
  267.                 Mov     AL,'\'                  ; For last slash
  268.                 Std                             ; Backwards search
  269.                 Repnz   Scasb                   ; Do it once
  270.                 Repnz   Scasb                   ; Again for dir we're leaving
  271.  
  272.                 Inc     DI                      ; So points to slash
  273.                 Mov     [SearchPointer],DI      ; New end of asciiz string
  274.                 Inc     [SearchPointer]         ; Actually one character more
  275.  
  276.                 Mov     SI,Offset SearchString  ; Now append \*.*,0 to it
  277.                 Mov     CX,5                    ; Five characters
  278.                 Cld                             ; In forward direction
  279.                 Rep     Movsb                   ; Move them int
  280.  
  281.                 Dec     [LevelsIn]              ; We go back one level
  282.                 Mov     [FirstOrNext],1         ; Have to search next, not 1st
  283.                 Sub     [DtaPointer],43         ; Previous DTA will be used
  284.                 Jmp     MainLoop                ; Back up to beginning
  285.  
  286. Terminate:      Int     20h                     ; Terminate program
  287.  
  288. ;       PrintChar subroutine -- prints a character on the screen
  289. ;       --------------------------------------------------------
  290.  
  291. PrintChar:      Push    DX
  292.  
  293.                 Mov     DL,AL           ; DL gets the character
  294.                 Mov     AH,2            ; Print character on display
  295.                 Int     21h             ;   by calling DOS
  296.  
  297.                 Pop     DX
  298.  
  299.                 Ret
  300.  
  301. ;       Other data areas here at end so COM file short as possible
  302. ;       ----------------------------------------------------------
  303.  
  304. SubDirCounter   Label   Word                            ; Counts dir entries
  305.  
  306. EndProg         equ     64 + Offset SubDirCounter       ; DTAs go here
  307.  
  308. CSEG            EndS
  309.  
  310.                 End Entry
  311.